﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tao.FreeGlut;
using Tao.OpenGl;
using AvantGameMachine.DataManagement;
using AvantGameMachine.Timers;

namespace AvantGameMachine.Graphics
{
    internal class OpenGLDevice
    {
        private int w;
        private int h;
        private Tempo FpsTempo;
        private int FPS = 0;
        private int currentFPS = 0;

        internal OpenGLDevice()
        {
        }

        private void init()
        {
            Gl.glShadeModel(Gl.GL_SMOOTH);     // Set the shading model to smooth 
            Gl.glClearColor(0, 0, 0, 1.0f);    // Clear the Color
            // Clear the Color and Depth Buffer
            Gl.glClear(Glut.GLUT_DEPTH | Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glClearDepth(1.0f);          // Set the Depth buffer value (ranges[0,1])
            Gl.glEnable(Gl.GL_DEPTH_TEST);  // Enable Depth test
            Gl.glDepthFunc(Gl.GL_LEQUAL);   // If two objects on the same coordinate 
            Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
        }

        internal void Init()
        {
            Glut.glutInit();        // Initialize glut
            // Setup display mode to double buffer and RGB color
            Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGBA | Glut.GLUT_ALPHA | Glut.GLUT_DEPTH);
            // Set the screen size
            w = AGMPlatform.CManager.GetConfigSize2D(new Address("resolution"), new Size2D(800, 600)).Width;
            h = AGMPlatform.CManager.GetConfigSize2D(new Address("resolution"), new Size2D(800, 600)).Height;
            Glut.glutInitWindowSize(w, h);
            Glut.glutCreateWindow("OpenGL 3D Navigation Program With Tao");
            init();
            Glut.glutReshapeFunc(reshape);
            Glut.glutDisplayFunc(DrawScene);
            Glut.glutWMCloseFunc(close);
            DeviceInfo info = new DeviceInfo();
            info.ShowDeviceInfo();
            // Set window's key callback
            AGMPlatform.IManager.RegisterCallbacks();
            AGMPlatform.TiManager.UpdateFrameTime();

            // Start timer for FPS.
            FpsTempo = AGMPlatform.TiManager.GetNewTempo(1000, true);
            FpsTempo.Start();
        }

        internal void mainloop()
        {
            Glut.glutMainLoop();
        }

        internal int ScreenW
        {
            get { return w; }
        }

        internal int ScreenH
        {
            get { return h; }
        }

        internal void reshape(int w, int h)
        {
            this.w = w;
            this.h = h;
            AGMPlatform.TopScene.ScreenW = w;
            AGMPlatform.TopScene.ScreenH = h;
            Glut.glutPostRedisplay();
        }

        internal void DrawScene()
        {
            // Clear the Color Buffer and Depth Buffer
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            AGMPlatform.StManager.Update();
            AGMPlatform.TopScene.InternalRender();

            // Check for the fps timer.
            if (FpsTempo.Ellapsed)
            {
                FpsTempo.Reset();
                FPS = currentFPS;
                currentFPS = 0;
                AGMPlatform.DVars.SetVar("FPS", FPS.ToString());
                Glut.glutSetWindowTitle(FPS.ToString());
            }

            Glut.glutSwapBuffers();
            currentFPS++;
            AGMPlatform.TiManager.UpdateFrameTime();
            Glut.glutPostRedisplay();           // Redraw the scene
        }

        internal void close()
        {
            Texture.DisposeAll();
        }
    }
}
